﻿// Copyright (c) 2010 Dan Popick

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Text.RegularExpressions;

namespace Open.Web.Stijl
{
    static class GeometricExtension
    {
        public static double Area(this Point p) { return Math.Sqrt((p.X * p.X) + (p.Y * p.Y)); }
        public static double DiagonalLength(this Point p) { return Math.Sqrt((p.X * p.X) + (p.Y * p.Y)); }
        public static double DiagonalLength(this Size size) { return ((Point)size).DiagonalLength(); }
    }

    static class IEnumerableExtension
    {
        public static TElement MinElement<TElement>(this IEnumerable<TElement> list, Func<TElement, double> selector)
        {
            double min = double.MaxValue;
            TElement minElement = default(TElement);

            foreach (TElement el in list) {
                double val = selector(el);
                if (val < min)
                {
                    min = val;
                    minElement = el;
                }
            }

            return minElement;
        }
    }

    static public class StringExtension
    {
        static Regex _escaped = new Regex(@"\\(.)", RegexOptions.Compiled);

        static public string Unquote(this string quotedString)
        {
            if (quotedString.StartsWith("'"))
                if (quotedString.EndsWith("'"))
                    return _escaped.Replace(quotedString.Substring(1, quotedString.Length - 2), "$1");
                else
                    return _escaped.Replace(quotedString.Substring(1), "$1");
            else if (quotedString.StartsWith( "\""))
                if (quotedString.EndsWith("\""))
                    return _escaped.Replace(quotedString.Substring(1, quotedString.Length - 2), "$1");
                else
                    return _escaped.Replace(quotedString.Substring(1), "$1");
            else
                return quotedString;
        }

		static public byte[] Encode(this string sourceString, EncodingType encoding)
		{
			uint crc32;
			return Encode(sourceString, encoding, out crc32);
		}

		static public byte[] Encode(this string sourceString, EncodingType encoding, out uint crc32)
		{
			byte[] asciiData = Encoding.ASCII.GetBytes(sourceString);

			Open.Web.Stijl.Utility.Crc32 crc = new Utility.Crc32();
			crc.ComputeHash(asciiData);
			crc32 = crc.CrcValue;

			if (EncodingType.deflate == (encoding & EncodingType.deflate))
			{
				MemoryStream outputString = new MemoryStream();
				DeflateStream ds = new DeflateStream(outputString, CompressionMode.Compress);
				ds.Write(asciiData, 0, asciiData.Length);
				ds.Close();
				return outputString.ToArray();
			}

			if (EncodingType.gzip == (encoding & EncodingType.gzip))
			{
				MemoryStream outputString = new MemoryStream();
				GZipStream ds = new GZipStream(outputString, CompressionMode.Compress);
				ds.Write(asciiData, 0, asciiData.Length);
				ds.Close();
				return outputString.ToArray();
			}

			return asciiData;
		}
	}

    static public class ColorExtensions
    {
        public static System.Windows.Media.Color ToMediaColor(this System.Drawing.Color color)
        {
            return new System.Windows.Media.Color()
            {
                A = color.A,
                R = color.R,
                G = color.G,
                B = color.B
            };
        }

        public static System.Drawing.Color ToDrawingColor(this System.Windows.Media.Color color)
        {
            return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B);
        }
    }

    static public class PixelFormatExtensions
    {
        public static bool IsIndexed(this System.Drawing.Imaging.PixelFormat format)
        {
            return ((int)format & (int)System.Drawing.Imaging.PixelFormat.Indexed) > 0;
        }
    }

	static public class IEnumerableExtensions
	{
		public static IEnumerable<T> Union<T>(this IEnumerable<T> e, T addon)
		{
			foreach (T x in e)
				yield return x;
			yield return addon;
		}
	}
}
